<?php

namespace System\Core;

use System\Lib\Log;
use \System\Types;

class UTF8 extends Types\Object
{

    /**
     * @var boolean
     */
    private static $_enabled = false;

    /**
     * @var boolean
     */
    private static $_mb_enabled = false;

    /**
     * @var UTF8
     */
    private static $_instance;

    /**
     * Constructor
     *
     * Determines if UTF-8 support is to be enabled
     */
    function __construct()
    {
        parent::__construct();
        Log::Write("UTF8 Class Initialized", Log::DEBUG);

        $CFG = Config::Get(\CFG_GENERAL);

        if (
                \preg_match('/./u', 'é') === 1     // PCRE must support UTF-8
                && \function_exists('iconv')     // iconv must be installed
                && \ini_get('mbstring.func_overload') != 1  // Multibyte string function overloading cannot be enabled
                && \strtoupper($CFG->Get('charset')->Valor) == 'UTF-8'   // Application charset must be UTF-8
        )
        {
            Log::Write('UTF-8 Support Enabled', Log::DEBUG);

            self::$_enabled = true;

            // set internal encoding for multibyte string functions if necessary
            // and set a flag so we don't have to repeatedly use extension_loaded()
            // or function_exists()
            if (\extension_loaded('mbstring'))
            {
                self::$_mb_enabled = true;
                \mb_internal_encoding('UTF-8');
            }
        }
        else
        {
            Log::Write('UTF-8 Support Disabled', Log::DEBUG);
        }
    }

    /**
     * @return boolean
     */
    public static function Utf8Enabled()
    {
        self::GetInstance();

        return self::$_enabled;
    }

    /**
     * @return boolean
     */
    public static function MbEnabled()
    {
        self::GetInstance();

        return self::$_mb_enabled;
    }

    // --------------------------------------------------------------------

    /**
     * Clean UTF-8 strings
     *
     * Ensures strings are UTF-8
     *
     * @access	public
     * @param	string
     * @return	string
     */
    function CleanString($str)
    {
        if ($this->IsASCII($str) === FALSE)
        {
            $str = @\iconv('UTF-8', 'UTF-8//IGNORE', $str);
        }

        return $str;
    }

    // --------------------------------------------------------------------

    /**
     * Remove ASCII control characters
     *
     * Removes all ASCII control characters except horizontal tabs,
     * line feeds, and carriage returns, as all others can cause
     * problems in XML
     *
     * @access	public
     * @param	string
     * @return	string
     */
    function SafeASCIIForXML($str)
    {
        return Types\String::RemoveInvisibleCharacters($str, false);
    }

    // --------------------------------------------------------------------

    /**
     * Convert to UTF-8
     *
     * Attempts to convert a string to UTF-8
     *
     * @access	public
     * @param	string
     * @param	string	- input encoding
     * @return	string
     */
    function ConvertToUtf8($str, $encoding)
    {
        if (\function_exists('iconv'))
        {
            $str = @\iconv($encoding, 'UTF-8', $str);
        }
        elseif (\function_exists('mb_convert_encoding'))
        {
            $str = @\mb_convert_encoding($str, 'UTF-8', $encoding);
        }
        else
        {
            return FALSE;
        }

        return $str;
    }

    /**
     * Is ASCII?
     *
     * Tests if a string is standard 7-bit ASCII or not
     *
     * @access	public
     * @param	string
     * @return	bool
     */
    function IsASCII($str)
    {
        return (\preg_match('/[^\x00-\x7F]/S', $str) == 0);
    }

    public static function &GetInstance()
    {
        if (!self::$_instance)
            self::$_instance = new self();

        return self::$_instance;
    }

}
